//
// Created by DELL on 2022/4/24.
//

#include "UniformBuffer.h"
#include "Device.h"

BEGIN_NS_VULKAN

UniformBuffer::UniformBuffer(DeviceRef device) : device(std::move(device)) {}

UniformBuffer::~UniformBuffer()
{
    if (this->buffer != nullptr)
    {
        vkDestroyBuffer(device->getDevice(), buffer, nullptr);
        buffer = nullptr;
    }
    if (this->memory != nullptr)
    {
        vkFreeMemory(device->getDevice(), memory, nullptr);
        memory = nullptr;
    }
}

UniformBufferRef UniformBuffer::create(DeviceRef& device, const UniformBlock& block)
{
    auto uniform = new UniformBuffer(device);
    uniform->init(block);
    return Vulkan::UniformBufferRef(uniform);
}

void UniformBuffer::init(const UniformBlock& block)
{
    this->name = block.name;
    this->binding = block.binding;
    this->size = block.size;
    this->fields = block.fields;
    this->bufferData.resize(block.size);

    device->createBuffer(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
                         this->buffer, this->memory);
}

void UniformBuffer::flush()
{
    vkMapMemory(device->getDevice(), this->memory, 0, this->size, 0, &mapData);
    memcpy(mapData, this->bufferData.data(), this->size);
    vkUnmapMemory(device->getDevice(), this->memory);
}

END_NS_VULKAN
